/*
 * Copyright (C) 2013 Mestrelab Research S.L. All rights reserved.
 *
 * This file is part of the Mnova scripting toolkit.
 *
 * Authorized users of MNova Software may use this file freely, but this file is provided AS IS
 * with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE.
 */

/*jslint  plusplus: true, indent: 4*/
/*global Application, MessageBox, qsTr, Dir, FileDialog, settings, print, serialization, NMRSpectrum, MnUi*/

function OpenEXPNOOptions(aCopy) {
	'use strict';
	this.EXPNO = '100';
	this.PROCNOs = '1, 2, 444';
	this.molecule = 'structure.mol';
	this.EXPNOFolder = Dir.home();
	this.layoutTemplatePath = '';

	this.readSettings();
	if (aCopy) {
		this.copy(aCopy);
	}
}

OpenEXPNOOptions.prototype = {
	SettingsKey: 'OpenEXPNO/Options',
	copy: function (aValue) {
		'use strict';
		var v;
		for (v in aValue) {
			if (aValue.hasOwnProperty(v)) {
				this[v] = aValue[v];
			}
		}
	},
	readSettings: function () {
		'use strict';
		var defStr = JSON.stringify(this),
			defValue = JSON.parse(settings.value(this.SettingsKey, defStr));
		this.copy(defValue);
	},
	writeSettings: function () {
		'use strict';
		settings.setValue(this.SettingsKey, JSON.stringify(this));
	}
};

function OpenEXPNODialog(aOpts) {
	'use strict';
	this.ui = Application.loadUiFile('ricares:OpenEXPNO.ui');
	if (!this.ui) {
		throw (qsTr('Unable to load UI'));
	}
	this.options = aOpts;
	this.initUi();
}

OpenEXPNODialog.prototype = {
	initUi: function () {
		'use strict';
		this.ui.widgets.fEXPNOLineEdit.text = this.options.EXPNO;
		this.ui.widgets.fPROCNOsLineEdit.text = this.options.PROCNOs;
		this.ui.widgets.fMoleculeLineEdit.text = this.options.molecule;
		this.ui.widgets.fEXPOsFolderLineEdit.text = this.options.EXPNOFolder;
		this.ui.widgets.fLayouTemplateLineEdit.text = this.options.layoutTemplatePath;

		this.ui.widgets.fEXPOsFolderToolButton.clicked.connect(this, 'getEXPOsFolder');
		this.ui.widgets.fLayouTemplateToolButton.clicked.connect(this, 'getLayoutTemplatePath');
	},
	exec: function () {
		'use strict';
		var retValue = this.ui.exec();
		this.done(retValue);
		return retValue;
	},
	done: function (aExitValue) {
		'use strict';
		if (aExitValue) {
			this.options.EXPNO = this.ui.widgets.fEXPNOLineEdit.text;
			this.options.PROCNOs = this.ui.widgets.fPROCNOsLineEdit.text;
			this.options.molecule = this.ui.widgets.fMoleculeLineEdit.text;
			this.options.EXPNOFolder = this.ui.widgets.fEXPOsFolderLineEdit.text;
			this.options.layoutTemplatePath = this.ui.widgets.fLayouTemplateLineEdit.text;
		}
	},
	getEXPOsFolder: function () {
		'use strict';
		var folder = this.ui.widgets.fEXPOsFolderLineEdit.text;
		if (!folder) {
			folder = Dir.home();
		}
		folder = FileDialog.getExistingDirectory(folder, qsTr('Select EXPO Directory'));
		if (folder) {
			this.ui.widgets.fEXPOsFolderLineEdit.text = folder;
		}
	},
	getLayoutTemplatePath: function () {
		'use strict';
		var layPath = this.ui.widgets.fLayouTemplateLineEdit.text;
		if (!layPath) {
			layPath = Dir.home();
		}
		layPath = FileDialog.getOpenFileName('MestReNova Document (*.mnova)', layPath, qsTr('Select Layout Template'));
		if (layPath) {
			this.ui.widgets.fLayouTemplateLineEdit.text = layPath;
		}
	}
};

function OpenEXPNOProcessor(aOpts) {
	'use strict';
	this.opts = aOpts;
	this.spcPaths = [];
	this.molfilePath = '';
	this.nmrItems = undefined;
	this.moleculeItem = undefined;
	this.docUuid = undefined;

	this.init();
}

OpenEXPNOProcessor.prototype = {
	init: function () {
		'use strict';
		var EXPNOsDirectory = new Dir(this.opts.EXPNOFolder),
			EXPNODir,
			spcFileName = '1r',
			PROCNODir,
			PROCNOsArr = this.opts.PROCNOs.match(/\d+/),
			i = 0;
		this.spcPaths = this.spcPaths.concat(this.findSpectra(EXPNOsDirectory, this.opts.EXPNO, this.opts.PROCNOs, '1r', true));
	},
	findSpectra: function (aEXPNOsDirectory, aEXPNO, aPROCNOsStr, aSpcFileName, aFindMolecule) {
		'use strict';
		var PROCNOsArr = aPROCNOsStr.match(/\d+/g),
			PROCNODir,
			EXPNODir,
			i,
			retArr = [],
			pdataDir;
		if (aEXPNOsDirectory.exists) {
			EXPNODir = new Dir(aEXPNOsDirectory.filePath(aEXPNO));
			if (EXPNODir.exists) {
				if (aFindMolecule) {
					if (EXPNODir.fileExists(this.opts.molecule)) {
						this.molfilePath = EXPNODir.filePath(this.opts.molecule);
					}
				}
				pdataDir = new Dir(EXPNODir.filePath('pdata'));
				if (pdataDir.exists) {
					for (i = 0; i < PROCNOsArr.length; ++i) {
						if (pdataDir.fileExists(PROCNOsArr[i])) {
							PROCNODir = new Dir(pdataDir.filePath(PROCNOsArr[i]));
							if (PROCNODir.fileExists(aSpcFileName)) {
								retArr.push(PROCNODir.filePath(aSpcFileName));
							}
						}
					}
				}
			}
		}
		return retArr;
	},
	isValid: function () {
		'use strict';
		return this.spcPaths.length && this.molfilePath.length;
	},
	openFiles: function () {
		'use strict';
		var doc = Application.mainWindow.activeDocument,
			i = 0,
			spcCount = 0;
		if (!doc || !doc.isValid() || doc.pageItems) {
			doc = Application.mainWindow.newDocument();
		}
		this.docUuid = doc.uuid;
		serialization.open(this.spcPaths);
		serialization.open(this.molfilePath);
		this.moleculeItem = doc.item(0, 'Molecule');
		spcCount = doc.itemCount('NMR Spectrum');
		this.nmrItems = [];
		for (i = 0; i < spcCount; ++i) {
			this.nmrItems.push(new NMRSpectrum(doc.item(i, 'NMR Spectrum')));
		}
		return this.moleculeItem && this.nmrItems.length;
	},
	process: function () {
		'use strict';
		var doc = this.getDocument();
		if (!doc) {
			MessageBox.critical(qsTr("Invalid Document"));
			return;
		}
		if (this.postOpen) {
			this.postOpen();
		}
		if (this.opts.layoutTemplatePath) {
			doc.applyTemplateDocument(this.opts.layoutTemplatePath);
		}
		return;
	},
	getDocument: function () {
		'use strict';
		try {
			Application.mainWindow.activeDocument = this.docUuid;
		} catch (er) {
			MessageBox.critical(qsTr("Invalid Document"));
			return null;
		}
		return Application.mainWindow.activeDocument;
	}
};

function OpenEXPNO() {
	'use strict';
	var opts = new OpenEXPNOOptions(),
		diag = new OpenEXPNODialog(opts),
		proc;
	if (diag.exec()) {
		opts.copy(diag.options);
		opts.writeSettings();
		proc = new OpenEXPNOProcessor(opts);
		if (proc.isValid()) {
			if (proc.openFiles()) {
				proc.process();
			}
		} else {
			MessageBox.critical(qsTr("Invalid Input"));
		}
	}
}

if (this.MnUi && MnUi.scripts_nmr) {
	MnUi.scripts_nmr.scripts_nmr_OpenEXPNO = OpenEXPNO;
}

